package com.linkelee.server.base.redis;



import com.linkelee.server.properties.RedisProperties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisPoolConfig;

/**
 * redis配置注册器
 *
 * @author lsl
 * @since 2019-03-25
 */


@Component
@ConfigurationProperties(prefix = "redis")
@Data
@Slf4j
public class JedisPoolConfigHelper implements InitializingBean {


    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private RedisProperties redisProperties;

    private JedisConnectionFactory jedisConnectionFactory;

    private JedisClientConfiguration jedisClientConfiguration;

    private int maxIdle;

    private int maxTotal;

    private int maxWaitMillis;

    private int minEvictableIdleTimeMillis;

    private int numTestsPerEvictionRun;

    private int timeBetweenEvictionRunsMillis;

    private boolean testOnBorrow;

    private boolean testWhileIdle;


    @Override
    public void afterPropertiesSet() {
        log.info("redis poolConfig init---");
        // 初始化jedis连接池信息
        initJedisPoolConfiguration();
        log.info("redis connection init---");
        // 初始化jedis信息
        initJedisConnectionFactory();
    }

    public void initJedisPoolConfiguration() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxIdle(maxIdle);
        poolConfig.setMaxTotal(maxTotal);
        poolConfig.setMaxWaitMillis(maxWaitMillis);
        poolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        poolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
        poolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        poolConfig.setTestOnBorrow(testOnBorrow);
        poolConfig.setTestWhileIdle(testWhileIdle);
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb =
                (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
        jpcb.poolConfig(poolConfig);
        jedisClientConfiguration = jpcb.build();
    }


    public void initJedisConnectionFactory() {
        // 如果存在哨兵参数,则初始化哨兵池
        if (Strings.isNotEmpty(redisProperties.getSentinels())) {
            log.info("redis Sentinels init--- ");
            initSentinelPool();
            return;
        }

        // 如果存在集群参数,则初始化集群池
        if (Strings.isNotEmpty(redisProperties.getClusters())) {
            log.info("redis Cluster init--- ");
            initClusterPool();
            return;
        }

        log.info("redis Standalone init--- ");
        // 初始化单例池
        initStandalonePool();
    }

    /**
     * 初始化单例池
     */
    private void initStandalonePool() {
        RedisStandaloneConfiguration redisStandaloneConfiguration
                = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setPort(redisProperties.getPort());
        redisStandaloneConfiguration.setHostName(redisProperties.getHost());
        log.info("redis standalone server init--- host:" + redisProperties.getHost() + ",port:" + redisProperties.getPort());
        log.info("redis server init--- choose database:" + redisProperties.getDataBase());
        redisStandaloneConfiguration.setDatabase(redisProperties.getDataBase());
        redisStandaloneConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
        jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }

    /**
     * 初始化哨兵池
     */
    private void initSentinelPool() {
        RedisNode masterNode = new RedisNode(redisProperties.getHost(), redisProperties.getPort());
        log.info("redis master server init--- host:" + redisProperties.getHost() + ",port:" + redisProperties.getPort());
        masterNode.setName(redisProperties.getMasterName());
        log.info("redis master server init--- masterName:" + redisProperties.getMasterName());
        String[] sentinelArray = redisProperties.getSentinels().split(",");
        RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration();
        redisSentinelConfiguration.setMaster(masterNode);
        for (String sentinelUrl : sentinelArray) {
            redisSentinelConfiguration.addSentinel(new RedisNode(sentinelUrl.split(":")[0],
                    Integer.parseInt(sentinelUrl.split(":")[1])));
            log.info("redis sentinel server addSentinel--- host:" + sentinelUrl.split(":")[0] + ",port:" + sentinelUrl.split(":")[1]);
        }
        redisSentinelConfiguration.setMaster(redisProperties.getMasterName());
        log.info("redis server init--- choose database:" + redisProperties.getDataBase());
        redisSentinelConfiguration.setDatabase(redisProperties.getDataBase());
        redisSentinelConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
        jedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration, jedisClientConfiguration);
    }

    //TODO 暂时不考虑集群池
    private void initClusterPool() {

    }
    public JedisConnectionFactory getJedisConnectionFactory() {
        if (jedisConnectionFactory == null) {
            afterPropertiesSet();
        }
        return jedisConnectionFactory;
    }
}
